package product.merchant;

import activity.ActivityProduct;
import activity.CustomActivityItem;
import com.google.gson.Gson;
import enums.GoodsStatus;
import enums.GoodsType;
import enums.ProductStatus;
import enums.ReviewStatus;
import goods.Goods;
import models.BaseModel;
import models.constants.DeletedStatus;
import models.merchant.Merchant;
import models.weixin.WebUser;
import order.AdminOrderItem;
import org.apache.commons.lang.StringUtils;
import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;
import play.Logger;
import play.db.jpa.JPA;
import product.ProductSpec;
import product.enums.DisableStatus;
import util.common.ConvertUtil;
import util.common.UStringUtil;
import util.list.ListUtil;
import util.list.enums.FilterType;
import util.list.models.FilterParam;

import javax.persistence.*;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 商品商户关系
 * Created by buhaoba on 16/6/16.
 */
@Entity
@Table(name = "product_spec_merchants")
public class ProductSpecMerchant extends BaseModel {

    public static final String CACHE_PRODUCTSPEC_MERCAHNT_ID = "ULC_CACHE_PRODUCTSPEC_MERCAHNT_ID_";
    public static final String REDIS_LOCK_KEY = "LOCAL_PRODUCT_SPEC_MERCHANT_LOCK";
    /**
     * 产品信息
     */
    @JoinColumn(name = "product_spec_id")
    @ManyToOne
    public ProductSpec productSpec;


    /**
     * 商户信息
     */
    @JoinColumn(name = "merchant_id")
    @ManyToOne
    public Merchant merchant;


    /**
     * 库存数量
     */
    @Column(name = "stock")
    public Double stock;

    /**
     * 是否需要监测库存 .
     * 如果需要监测库存. 那么 销售数量必须为库存数量
     * 不检测库存 可以先销售 . 库存可为负数
     * true 表示不允许超卖
     */
    @Column(name = "check_stock")
    public Boolean checkStock;


    /**
     * 最大预售量
     */
    @Column(name = "max_advance")
    public Double maxAdvance;


    /**
     * 商品上下架状态
     */
    @Column(name = "product_status")
    @Enumerated(EnumType.STRING)
    public ProductStatus productStatus;

    /**
     * 审核状态
     */
    @Column(name = "review_status")
    @Enumerated(EnumType.STRING)
    public ReviewStatus reviewStatus;


    /**
     * 建议零售价
     */
    @Column(name = "price")
    public Double price = 0D;


    /**
     * 市场价格
     */
    @Column(name = "market_price")
    public Double marketPrice = 0D;

    /**
     * 合伙人价格
     */
    @Column(name = "partner_price")
    public Double partnerPrice = 0D;

    /**
     * 商户自定义价格
     */
    @Column(name = "merchant_price")
    public Double merchantPrice = 0D;

    /**
     * 做促销时候 展示原价使用
     */
    @Column(name = "old_price")
    public Double oldPrice = 0d;


    /**
     * 可购买次数
     * 主要针对 某个产品只能购买一次
     * 通过数量解决 可购买 限定次数的问题
     */
    @Column(name = "can_buy_count")
    public Integer canBuyCount = 1000000;


    /**
     * 排序号
     */
    @Column(name = "show_order")
    public Long showOrder;


    /**
     * 最大购买数量
     */
    @Column(name = "max_num")
    public Integer maxNum;


    /**
     * 最小购买量
     */
    @Column(name = "min_num")
    public Integer minNum = 1;

    /**
     * 每次点击跳跃数量 前台客户点击一下 增加数量
     */
    @Column(name = "jump_num")
    public Integer jumpNum;

    /**
     * 单日最大购买次数
     * */
    @Column(name = "day_buy_num")
    public Integer dayBuyNum;
    /**
     * 是否预售
     */
    @Column(name = "pre_sale")
    public Boolean preSale;

    /**
     * 预计发货时间
     */
    @Column(name = "estimate_send_date")
    @Temporal(TemporalType.TIMESTAMP)
    public Date estimateSendDate;

    @Transient
    public String estimateSendDateStr;

    /**
     * 创建时间
     */
    @Column(name = "created_at")
    @Temporal(TemporalType.TIMESTAMP)
    public Date createdAt;

    /**
     * 逻辑删除,0:未删除，1:已删除
     */
    @Enumerated(EnumType.ORDINAL)
    public DeletedStatus deleted;

    @Column(name = "remark")
    public String remark;

    /**
     * 单位
     */
    @Column(name = "unit")
    public String unit;

    /**
     * 数量
     */
    @Column(name = "num")
    public Double num = 0D;

    /**
     * 平均价格
     */
    @Column(name = "avg_price")
    public Double avgPrice = 0D;

    /**
     * 该商户产品销售数量
     */
    @Column(name = "sales_numbers")
    public Double salesNumbers = 0D;


    /**
     * 商户商品展示图片
     */
    @Column(name = "main_image")
    public String mainImage;



    public Goods findGoods() {
        return Goods.find("type = ? and  serialId = ? and deleted = ? and salePrice = ？", GoodsType.PRODUCT, this.id, DeletedStatus.UN_DELETED ).first();
    }



    public Goods findGoods(WebUser webUser) {
        Logger.info("Log 1011010 WebUser : %s" , webUser);
        Double price = this.merchantPrice;
        ProductSpecMerchantPriceGroupWebUser priceGroupWebUser = ProductSpecMerchantPriceGroupWebUser.findBySpecMerchantIdAndWebUser(this.id , webUser);
        if(priceGroupWebUser != null) {
            price = priceGroupWebUser.priceGroup.price;
        }
        Goods goods = Goods.find("type = ? and serialId = ? and deleted = ? and salePrice = ?", GoodsType.PRODUCT, this.id, DeletedStatus.UN_DELETED , price).first();
//        Logger.info("LOG 1011011  Goods : %s" , goods);
        if(goods == null && priceGroupWebUser != null) {
            goods = findOrCreateGoods(priceGroupWebUser.priceGroup);
            Logger.info("LOG 1011012  Goods : %s" , goods);
        }

        if(goods == null) {
            goods = findOrCreateGoods();
            Logger.info("LOG 1011012  Goods : %s" , goods);
        }

        Logger.info("LOG 1011013  Goods : %s" , goods);
        return goods;
    }


    /**
     * 构建 Goods
     *
     * @return
     */
    public Goods findOrCreateGoods() {
        Goods goods = Goods.find("type = ? and  serialId = ? and deleted = ?", GoodsType.PRODUCT, this.id, DeletedStatus.UN_DELETED).first();
        if (goods == null) {
            goods = new Goods();
            goods.createdAt = new Date();
            goods.name = this.productSpec.product.name;
            goods.deleted = DeletedStatus.UN_DELETED;
            goods.type = GoodsType.PRODUCT;
            goods.status = GoodsStatus.OPEN;
            goods.serialId = this.id;
            goods.salePrice = this.merchantPrice;
            goods.img = this.productSpec.mainImage;
            //goods.spec = this.productSpec.spec;
            //goods.unit = this.productSpec.unit;
            //goods.maxNum = this.maxNum;
            //goods.code = this.productSpec.barCode;
            goods.save();
        } else {
            goods.name = this.productSpec.product.name;
            goods.deleted = DeletedStatus.UN_DELETED;
            goods.status = GoodsStatus.OPEN;
            goods.serialId = this.id;
            goods.salePrice = this.merchantPrice;
            goods.img = this.productSpec.mainImage;
//            goods.spec = this.productSpec.spec;
//            goods.unit = this.productSpec.unit;
//            goods.maxNum = this.maxNum;
//            goods.code = this.productSpec.barCode;
            goods.save();
        }
        return goods;
    }


    /**
     * 构建 Goods
     *
     * @return
     */
    public Goods findOrCreateGoods(ProductSpecMerchantPriceGroup priceGroup) {
        Goods goods = Goods.find("type = ? and  serialId = ? and salePrice = ? and  deleted = ?", GoodsType.PRODUCT, this.id, priceGroup.price, DeletedStatus.UN_DELETED).first();
        if (goods == null) {
            goods = new Goods();
            goods.createdAt = new Date();
            goods.name = this.productSpec.product.name;
            goods.deleted = DeletedStatus.UN_DELETED;
            goods.type = GoodsType.PRODUCT;
            goods.status = GoodsStatus.OPEN;
            goods.serialId = this.id;
            goods.salePrice = priceGroup.price;
            goods.img = this.productSpec.mainImage;
//            goods.spec = this.productSpec.spec;
//            goods.unit = this.productSpec.unit;
//            goods.maxNum = this.maxNum;
//            goods.code = this.productSpec.barCode;
            goods.save();
        } else {
            goods.name = this.productSpec.product.name;
            goods.deleted = DeletedStatus.UN_DELETED;
            goods.status = GoodsStatus.OPEN;
            goods.serialId = this.id;
            goods.salePrice = priceGroup.price;
            goods.img = this.productSpec.mainImage;
//            goods.spec = this.productSpec.spec;
//            goods.unit = this.productSpec.unit;
//            goods.maxNum = this.maxNum;
//            goods.code = this.productSpec.barCode;
            goods.save();
        }
        return goods;
    }



    /**
     * 根据ID查询商户产品
     *
     * @param id
     * @return
     */
    public static ProductSpecMerchant findBySpecMerchantId(long id) {
        return ProductSpecMerchant.find("id=? and deleted=?", id, DeletedStatus.UN_DELETED).first();
    }

    /**
     * 根据ID查询商户上架产品
     *
     * @param id
     * @return
     */
    public static ProductSpecMerchant findByIdAndUp(long id) {
        return ProductSpecMerchant.find("id=? and deleted=? and productStatus = ?", id, DeletedStatus.UN_DELETED ,ProductStatus.UP).first();
    }


    /**
     * 根据产品ID查询产品的规格型号列表
     *
     * @param id
     * @return
     */
    public static List<ProductSpecMerchant> getProSpecList(long id, Merchant merchant) {
        return ProductSpecMerchant.find("productSpec.product.id=? and merchant = ? and deleted = ? and productStatus = ? ", id, merchant, DeletedStatus.UN_DELETED, ProductStatus.UP).fetch();
    }

    /**
     * 上下架
     * @param ids
     * @param productStatus
     */
    public static void productStatusChange(Integer[] ids, ProductStatus productStatus) {
        if (ProductStatus.DOWN.equals(productStatus))
            checkIsActivity(ids);

        String sql = "update product_spec_merchants set product_status = ? where id in (" + UStringUtil.concatStr(",", ids) + ")";
        em().createNativeQuery(sql).setParameter(1, productStatus.toString()).executeUpdate();
    }

    //下架之前需检查是否有参加促销,秒杀等活动的商品,如果有,强制退出活动,预售除外
    public static void checkIsActivity(Integer[] specMerchantIdArrary) {
        Logger.info("LOG30002 : checkIsActivity : specMerchantIdArrary %s ", specMerchantIdArrary);
        //下架之前需检查是否有参加促销,秒杀等活动的商品,如果有,强制退出活动,预售除外,
        // 检索CustomActivityItem
        List<Map<String, Object>> activityItemList = CustomActivityItem.loadByProductSpecMerchantId(specMerchantIdArrary);
        Logger.info("LOG30002 : checkIsActivity : activityItemList %s ", new Gson().toJson(activityItemList));
        for (Map<String, Object> customActivityItem : activityItemList) {
            CustomActivityItem activityItem = CustomActivityItem.findById(ConvertUtil.toLong(customActivityItem.get("id")));

            activityItem.deleted = DeletedStatus.DELETED;
            activityItem.save();
        }
        //检索ActivityProduct
        List<Map<String, Object>> activityProductList = ActivityProduct.loadBySpecMerchantId(specMerchantIdArrary);
        Logger.info("LOG30003 : checkIsActivity : activityProductList %s ", new Gson().toJson(activityProductList));
        for (Map<String, Object> activityProduct : activityProductList) {
            ActivityProduct activityPro = ActivityProduct.findById(ConvertUtil.toLong(activityProduct.get("id")));
            activityPro.deleted = DeletedStatus.DELETED;
            activityPro.save();
        }
    }

    @Transient
    public String getRedisLockKey() {
        return ProductSpecMerchant.REDIS_LOCK_KEY + this.id + "@product_spec_merchant";
    }


    /**
     * 监测用户购买数量 是否大于库存数量
     * 用户 要购买的数量  + Redis中锁的数量  是否大于 库存数量
     *
     * @param productSpecMerchant 用户要购买的商品信息
     * @param count               //用户要购买的数量
     * @return
     */
    public static Boolean checkRedis(ProductSpecMerchant productSpecMerchant, Integer count) {
//        count = count == null ? 0 : count;
//        //Redis中存储的数量
//        String redisProductCount = Redis.get(productSpecMerchant.getRedisLockKey());
//        Integer sumCount = count;
//
//        // 如果以前的不为空.  那么 redis 锁定的数量为  以前redis中的 加  当前购买的
//        if (StringUtils.isNotBlank(redisProductCount)) {
//            sumCount = count + Integer.parseInt(redisProductCount);
//        }
//        // 当前 sumCount 为redis 中的 外加 当前购买的数量
//        //如果 库存为null 设置库存为0 . 防止报错
//        productSpecMerchant.stock = productSpecMerchant.stock == null ? 0d : productSpecMerchant.stock;
//        // 如果必须验证库存 并且 购买数量 + redis数量 大于 库存数量. 则不可以购买
//        if (productSpecMerchant.checkStock != null && productSpecMerchant.checkStock && sumCount > productSpecMerchant.stock)
//            return false;
//
//        // 如果不需要验证库存  并且 购买数量 + Redis 数量 大于 库存数量 + 可预售数量 , 则不可以购买
//        if (productSpecMerchant.checkStock != null && !productSpecMerchant.checkStock && sumCount > (productSpecMerchant.stock + productSpecMerchant.maxAdvance))
//            return false;

        return true;
    }


    /**
     * 商品加到 redis 中
     *
     * @param productSpecMerchant
     * @param count
     */
    public static void addRedisProduct(ProductSpecMerchant productSpecMerchant, Integer count) {
//        count = count == null ? 0 : count;
//        String redisProductCount = Redis.get(productSpecMerchant.getRedisLockKey());
//        Integer sumCount = count;
//        // 如果以前的不为空.  那么 redis 锁定的数量为  以前redis中的 加  当前购买的
//        if (StringUtils.isNotBlank(redisProductCount)) {
//            sumCount = count + Integer.parseInt(redisProductCount);
//        }
//        Redis.setex(productSpecMerchant.getRedisLockKey(), 15 * 60, sumCount.toString());
//        Logger.info("放入Redis中商品数量:%s", Redis.get(productSpecMerchant.getRedisLockKey()));
    }


    /**
     * 商品从 redis 中扣除
     *
     * @param productSpecMerchant
     * @param count
     */
    public static void subtractRedis(ProductSpecMerchant productSpecMerchant, Integer count) {
//        count = count == null ? 0 : count;
//        String redisProductCount = Redis.get(productSpecMerchant.getRedisLockKey());
//        Integer sumCount = count;
//        // 如果以前的不为空.  那么 redis 锁定的数量为  以前redis中的 加  当前购买的
//        if (StringUtils.isNotBlank(redisProductCount)) {
//            sumCount = Integer.parseInt(redisProductCount) - count;
//        }
//        Redis.setex(productSpecMerchant.getRedisLockKey(), 15 * 60, sumCount.toString());
//        Logger.info("订单取消或支付后, Redis中减掉相应数量 防止根据时间重复加载. %s在Redis现存数量为:%s", productSpecMerchant.productSpec.product.name + " " + productSpecMerchant.productSpec.spec, Redis.get(productSpecMerchant.getRedisLockKey()));
    }


    /**
     * 从缓存中根据ID查实体
     *
     * @param id
     * @return
     */
    public static ProductSpecMerchant findByCacheId(long id) {
        return ProductSpecMerchant.find("deleted = ? and id = ? and productStatus = ? ", DeletedStatus.UN_DELETED, id, ProductStatus.UP).first();
//        return CacheHelper.getCache(CACHE_PRODUCTSPEC_MERCAHNT_ID+id, new CacheCallBack<ProductSpecMerchant>() {
//            @Override
//            public ProductSpecMerchant loadData() {
//                return ProductSpecMerchant.find("deleted = ? and id = ? and productStatus = ? ", DeletedStatus.UN_DELETED, id,ProductStatus.UP).first();
//            }
//        });
    }

    /**
     * 当自营的商铺销售产品后
     * 自营的所有店 都需要更新库存. 跟仓库库存一致
     *
     * @param stock
     * @param specId
     */
    public static void synSelfSupportStock(Integer stock, Long specId) {
        StringBuilder hql = new StringBuilder();
        hql.append("update ProductSpecMerchant psm set psm.stock = :stock where psm.productSpec.id = :specId");
        Query query = JPA.em().createQuery(hql.toString());
        query.setParameter("stock", stock);
        query.setParameter("specId", specId);
        query.executeUpdate();
    }

    public static List<ProductSpecMerchant> findByProductSpecId(long id) {
        return ProductSpecMerchant.find(" productSpec.id = ? and deleted = ? and merchant.deleted = ? ", id, DeletedStatus.UN_DELETED, DeletedStatus.UN_DELETED).fetch();
    }

    /**
     * 查询某商户是否含有某款商品
     *
     * @param productSpecId
     * @param merchantId
     * @return
     */
    public static ProductSpecMerchant findByProductSpecIdAndMerchantId(long productSpecId, long merchantId) {
        return ProductSpecMerchant.find(" productSpec.id = ? and deleted = ? and merchant.id = ?  ", productSpecId, DeletedStatus.UN_DELETED, merchantId).first();
    }

    //根据产品规格Id获取商户商品集合
    public static List<ProductSpecMerchant> loadBySpecId(Integer[] SpecIdArray) {
        String specIdStr = UStringUtil.concatStr(",", SpecIdArray);
        return ProductSpecMerchant.find(" deleted=? and productSpec.id in (" + specIdStr + ")", DeletedStatus.UN_DELETED).fetch();
    }

    //根据商户商品Id获取商户商品集合
    public static List<ProductSpecMerchant> loadBySpecMerchantId(Integer[] delItemArray) {
        String delItemStr = UStringUtil.concatStr(",", delItemArray);
        return ProductSpecMerchant.find(" deleted=? and id in (" + delItemStr + ")", DeletedStatus.UN_DELETED).fetch();
    }

    //根据ID删除操作明细
    public static void delByIds(Integer[] delItemArray) {
        List<ProductSpecMerchant> productSpecMerchants = loadBySpecMerchantId(delItemArray);
        for (ProductSpecMerchant productSpecMerchant : productSpecMerchants) {
            productSpecMerchant.deleted = DeletedStatus.DELETED;
            productSpecMerchant.save();
        }
//        ProductSpecMerchant.delete("id in (" + delItemStr + ")");
    }

    public static List<HashMap<String, Object>> findByMerchantAndType(Merchant merchant, long id) {
//        Query query = em().createNativeQuery("SELECT DISTINCT m.id,p.name as name, ps.spec as spec, m.merchant_price as merchantPrice,ps.main_image as mainImage  FROM product_spec_merchants m LEFT JOIN product_specs ps ON m.product_spec_id = ps.id LEFT JOIN products p ON ps.product_id = p.id LEFT JOIN product_types pt ON p.id = pt.product_id LEFT JOIN product_type t ON pt.type_id = t.id WHERE pt.type_id = "+id+" AND m.merchant_id = "+merchant.id +" and m.deleted = 0 and pt.deleted = 0 and m.product_status = 'UP' and m.review_status = 'PASS' order by t.sort asc,t.id ");
        Logger.info("LOG: 000100010 findByFirstlevelAndMerchant");
        Query query = em().createNativeQuery("SELECT m.id,p.name as name, p.selling_point as sellingPoint, p.show_price as merchantPrice,p.main_image as mainImage , p.id as productId , FORMAT(m.avg_price , 2) as avgPrice , m.unit as unit  FROM product_spec_merchants m LEFT JOIN product_specs ps ON m.product_spec_id = ps.id LEFT JOIN products p ON ps.product_id = p.id LEFT JOIN product_types pt ON p.id = pt.product_id LEFT JOIN product_type t ON pt.type_id = t.id WHERE pt.type_id = " + id + " AND m.merchant_id = " + merchant.id + " and m.deleted = 0 and pt.deleted = 0 and m.product_status = 'UP' group by p.id order by m.show_order,t.sort asc,t.id ");
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        return query.getResultList();
    }

    public static List<HashMap<String, Object>> findByFirstlevelAndMerchant(Merchant merchant, long id, int pageNum) {
//        Query query = em().createNativeQuery("SELECT DISTINCT m.id, p.name AS name, ps.spec AS spec, m.merchant_price AS merchantPrice, ps.main_image AS mainImage, t.name AS typename FROM product_spec_merchants m LEFT JOIN product_specs ps ON m.product_spec_id = ps.id LEFT JOIN products p ON ps.product_id = p.id LEFT JOIN product_types pt ON p.id = pt.product_id LEFT JOIN product_type t ON pt.type_id = t.id WHERE ((t.level =3 and t.parent_type_id="+id+") or (t.level=2 and t.id = "+id+"))  AND m.merchant_id = "+merchant.id+" AND m.deleted = 0 AND pt.deleted = 0 and m.product_status = 'UP' and m.review_status = 'PASS' order by t.sort asc,t.id desc LIMIT "+pageNum+", 10");
        Logger.info("LOG: 000100011 findByFirstlevelAndMerchant");
        Query query = em().createNativeQuery("SELECT m.id, p.name AS name, p.selling_point AS sellingPoint, p.show_price AS merchantPrice, p.main_image AS mainImage, t.name AS typename , p.id as productId , FORMAT(m.avg_price , 2) as avgPrice , m.unit as unit FROM product_spec_merchants m LEFT JOIN product_specs ps ON m.product_spec_id = ps.id LEFT JOIN products p ON ps.product_id = p.id LEFT JOIN product_types pt ON p.id = pt.product_id LEFT JOIN product_type t ON pt.type_id = t.id WHERE ((t.level =3 and t.parent_type_id=" + id + ") or (t.level=2 and t.id = " + id + "))  AND m.merchant_id = " + merchant.id + " AND m.deleted = 0 AND pt.deleted = 0 and m.product_status = 'UP' group by p.id order by t.sort asc LIMIT " + pageNum + ", 10");
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        return query.getResultList();
    }

    /**
     * @param merchant
     * @param nodeIdPath
     * @param pageNum
     * @param order      0：常规 1.销量 2.价格 3.时间
     * @return
     */
    public static Map<String, Object> findByNodeIdPath(Merchant merchant, String nodeIdPath, int pageNum, int order, int sort, Double minPrice, Double maxPrice) {

        int pageSize = 15;
        String baseOrder = "m.show_order,m.id";
        String priceWhere = "";
        pageNum = (pageNum - 1) * pageSize;
        if (order == 1) {
            baseOrder = "m.sales_numbers " + (sort == 1 ? "asc" : "desc") + "," + baseOrder;
        } else if (order == 2) {
            baseOrder = "m.merchant_price " + (sort == 1 ? "asc" : "desc") + "," + baseOrder;
        } else if (order == 3) {
            baseOrder = "m.create_at " + (sort == 1 ? "asc" : "desc") + "," + baseOrder;
        }

        if (minPrice != null) {
            priceWhere += " and m.merchant_price>=" + minPrice;
        }

        if (maxPrice != null) {
            priceWhere += " and m.merchant_price<=" + maxPrice;
        }


        Map<String, Object> listData = new HashMap<String, Object>();
        Query query = em().createNativeQuery("SELECT m.id, p.name AS prodName, ps.spec,concat(p.name,'(',ps.spec,')') as name,ps.main_image, FORMAT(m.merchant_price,2) as merchantPrice,t.name AS typename , p.id as productId , m.unit as unit FROM product_spec_merchants m LEFT JOIN product_specs ps ON m.product_spec_id = ps.id LEFT JOIN products p ON ps.product_id = p.id LEFT JOIN product_types pt ON p.id = pt.product_id LEFT JOIN product_type t ON pt.type_id = t.id WHERE m.merchant_id = " + merchant.id + " AND m.deleted = 0 AND pt.deleted = 0 and m.product_status = 'UP' " + priceWhere + " and t.node_id_path like '" + nodeIdPath + "%' order by " + baseOrder + " asc LIMIT " + pageNum + "," + pageSize);
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        listData.put("data", query.getResultList());
        Query countQuery = em().createNativeQuery("SELECT count(1) as total FROM product_spec_merchants m LEFT JOIN product_specs ps ON m.product_spec_id = ps.id LEFT JOIN products p ON ps.product_id = p.id LEFT JOIN product_types pt ON p.id = pt.product_id LEFT JOIN product_type t ON pt.type_id = t.id WHERE m.merchant_id = " + merchant.id + " AND m.deleted = 0 AND pt.deleted = 0 and m.product_status = 'UP' " + priceWhere + " and t.node_id_path like '" + nodeIdPath + "%'");
        Double total = ConvertUtil.toDouble(countQuery.getSingleResult());
        listData.put("total", ConvertUtil.toInteger(total));
        int pages = (int) Math.ceil(total / pageSize);
        listData.put("pages", pages);
        return listData;
    }


    public static ProductSpecMerchant findMinPriceByProduct(Long productId, Merchant merchant) {
        return ProductSpecMerchant.find("deleted = ? and productSpec.product.id = ? and merchant = ? and productStatus = ? order by merchantPrice asc", DeletedStatus.UN_DELETED, productId, merchant, ProductStatus.UP).first();
    }

    public static ProductSpecMerchant findMaxPriceByProduct(Long productId, Merchant merchant) {
        return ProductSpecMerchant.find("deleted = ? and productSpec.product.id = ? and merchant = ? and productStatus = ? order by merchantPrice desc", DeletedStatus.UN_DELETED, productId, merchant, ProductStatus.UP).first();
    }

    public static List<Map<String, Object>> findMinPriceByProductIn(String productIds, Merchant merchant) {
        StringBuilder sql = new StringBuilder();
        sql.append(" SELECT DISTINCT m.id as specProductId, m.merchant_price as merchantPrice,ps.main_image as mainImage,p.name as name,m.unit AS unit,ps.spec as spec,m.old_price as oldPrice ,ps.id as specId , m.num as num FROM product_spec_merchants m LEFT JOIN product_specs ps ON m.product_spec_id = ps.id LEFT JOIN products p ON ps.product_id = p.id ");
        sql.append(" where  m.deleted = 0 and m.product_status = 'UP' and merchant_id = "+merchant.id+" And ps.id in (").append(productIds).append(") order by field(ps.id,").append(productIds);
        sql.append(" ) ");
        Query query = JPA.em().createNativeQuery(sql.toString());
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List<Map<String, Object>> productSpecMerchants = query.getResultList();
//         return ProductSpecMerchant.find("deleted = ? and productSpec.product.id in ( ? ) and merchant = ? and productStatus = ? order by merchantPrice asc", DeletedStatus.UN_DELETED, productIds, merchant, ProductStatus.UP).first();
        return productSpecMerchants;
    }

    /**
     * 商品加到 redis 中
     *
     * @param productSpecMerchant
     * @param count
     */
    public static void subtractRedisProduct(ProductSpecMerchant productSpecMerchant, Integer count) {
//        count = count == null ? 0 : count;
//        String redisProductCount = Redis.get(productSpecMerchant.getRedisLockKey());
//        Integer sumCount = count;
//        // 如果以前的不为空.  那么 redis 锁定的数量为  以前redis中的 加  当前购买的
//        if (StringUtils.isNotBlank(redisProductCount)) {
//            sumCount = Integer.parseInt(redisProductCount) - count;
//        }
//        Redis.setex(productSpecMerchant.getRedisLockKey(), 15 * 60, sumCount.toString());
//        Logger.info("订单取消后, Redis中减掉相应数量 防止根据时间重复加载. %s在Redis现存数量为:%s", productSpecMerchant.productSpec.product.name, Redis.get(productSpecMerchant.getRedisLockKey()));
    }

    /**
     * 查询所有可用的商户产品
     *
     * @return
     */
    public static List<ProductSpecMerchant> findAvailable() {
        return ProductSpecMerchant.find("deleted = ? and productStatus = ?", DeletedStatus.UN_DELETED, ProductStatus.UP).fetch();
    }

    /**
     * 查询所有可用的商户产品
     *
     * @return
     */
    public static List<ProductSpecMerchant> findTenAvailable() {
        return ProductSpecMerchant.find("deleted = ? and productStatus = ? and stock > 0", DeletedStatus.UN_DELETED, ProductStatus.UP).fetch(10);
    }

    /**
     * 查询某商品的兄弟规格商品(同一商户 同一产品下 不同规格)
     *
     * @param specMerchant
     * @return
     */
    public static List<ProductSpecMerchant> loadByProductSpecMerchant(ProductSpecMerchant specMerchant) {
        Long merchantId = ConvertUtil.toLong(specMerchant.merchant.id);
        Long productId = ConvertUtil.toLong(specMerchant.productSpec.product.id);

        return ProductSpecMerchant.find("deleted = 0 and  productSpec.product.id = ? and productSpec.deleted = 0 and merchant.id = ? and productStatus = ?", productId, merchantId, ProductStatus.UP).fetch();
    }

    public static List<Map<String, Object>> loadTop6(long merchantId) {
        String sqlSelect = "select  c.id, e.name,d.spec, c.merchant_price,sum(ifnull(a.buy_number,0)) as count , d.main_image  " +
                " from admin_order_item a  " +
                " left join admin_order f on a.admin_order = f.id " +
                " left join goods b on a.goods_id = b.id  " +
                " left join product_spec_merchants c on b.serial_id = c.id   " +
                " left join product_specs d on c.product_spec_id = d.id  " +
                " left join products e on d.product_id = e.id " +
                " where a.deleted = 0 " +
                "   and c.deleted = 0 " +
                "   and d.deleted = 0  " +
                "   and f.to_track = 1 " +
                "   and f.deleted = 0  " +
                "   and c.product_status = 'UP' " +
                "   and c.merchant_id =  " + merchantId +
                " group by c.id,e.name,d.spec  " +
                " order by count desc limit 0,6";

        Query query = AdminOrderItem.em().createNativeQuery(sqlSelect);
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List<Map<String, Object>> top5List = query.getResultList();

        return top5List;
    }


    /**
     * 检测产品是否是禁用产品
     * @param ids
     */
    public static String checkDisableStatus(Integer[] ids){
        String str ="";
        List<ProductSpecMerchant> specMerchantList = ProductSpecMerchant.find("productSpec.disableStatus = ? and id in ("+ UStringUtil.concatStr(",",ids) +")", DisableStatus.DISABLE).fetch();
        if(specMerchantList.size()>0){
            for(ProductSpecMerchant specMerchant : specMerchantList){
                str = specMerchant.productSpec.product.name+specMerchant.productSpec.spec+",";
            }
        }
        return str;

    }

    /**
     * 根据id数组查询商品
     * @param ids
     */
    public static List<ProductSpecMerchant> loadByids(Integer[] ids){
        return ProductSpecMerchant.find(" id in ("+ UStringUtil.concatStr(",",ids) +")").fetch();
    }


}
